package cn.com.counter.core;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import cn.com.counter.container.BaseContainer;
import cn.com.counter.container.BufferContainer;
import cn.com.counter.container.Counts;

/**
 * 请以单例模式调用
 * @author yyq
 */
public abstract class Counter {

	private BufferContainer counterContainer = new BaseContainer();
	private Long MAX_BUFFER_COUNT = 20L;
	
	/**
	 * 每个缓存的最大存储次数，默认为20
	 * @param count
	 */
	public void initMaxBufferCount(Long count){
		MAX_BUFFER_COUNT = count;
	}
	
	/**
	 * 设置存储计数的缓存容器。
	 * 只需设置一次
	 * @param container
	 */
	public void setBufferContainer(BufferContainer container){
		counterContainer = container;
	}
	
	/**
	 * 计数次数增长
	 * @param counterId
	 */
	public void incCounts(long counterId){
		Counts counts = findCounts( counterId );
		if(counts!=null){
			updateCounts( counterId );
		}
	}
	
	/**
	 * 获取指定counterId的次数，默认container在负载均衡的环境中无法正常使用
	 * @param counterId
	 * @return
	 */
	public long getCurrentCounts(long counterId){
		return getCurrentCounts( counterId, true );
	}
	
	/**
	 * 获取指定counterId的次数
	 * @param counterId
	 * @param containBuffer false时， 默认container在负载均衡的环境中无法正常使用
	 * @return
	 */
	public long getCurrentCounts(long counterId, boolean containBuffer){
		Counts counts = findCounts( counterId );
		if(counts==null){
			return 0;
		}
		if(containBuffer){
			return counts.getDbCounts()+counts.getBufferCounts();
		}else{
			return counts.getDbCounts();
		}
		
	}
	
	/**
	 * 更新所有缓存数据到数据库
	 */
	public void updateAllBuffer2Db(){
		Set<Long> sets = counterContainer.keySet();
		for( Long key : sets) {
	        updateCounts2Db( key );
        }
	}
	
	/**
	 * 更新数据库或者缓存数据
	 * @param counterId
	 * @param counts
	 */
	private void updateCounts(long counterId){
		Counts counts = counterContainer.get( counterId );
		synchronized( counts ) {
			if(counts.getBufferCounts()>=(MAX_BUFFER_COUNT-1)){
				counts.setBufferCounts( counts.getBufferCounts()+1 );
				updateCounts2Db( counterId );
				
				long num = findConutsInDb( counterId );
	        	counts.setBufferCounts( 0 );	//当前次数
	        	counts.setDbCounts( num );
			}else{
				counts.setBufferCounts( counts.getBufferCounts()+1 );
			}
        }
	}
	
	/**
	 * 从map或者db中找counter数据
	 * @param counterId
	 * @return
	 */
	private Counts findCounts(long counterId){

		Counts counts = counterContainer.get( counterId );
		if(counts==null){
			long num = findConutsInDb( counterId );
	        if(num>0){
	        	counts = new Counts();
	        	counts.setBufferCounts( 0 );
	        	counts.setDbCounts( num );
	        }
		}
		if(counts==null){
			System.out.println("id="+counterId+" 的counter数据不存在");
		}else{
			counterContainer.put( counterId, counts );
		}
		return counts;
	}

	/**
	 * 更新数据到数据库
	 * @param counterId
	 * @param counts
	 */
	public abstract void updateCounts2Db(long counterId );
	
	/**
	 * 找出counter中指定id的数据
	 * @param counterId
	 * @return
	 */
	public abstract long findConutsInDb(long counterId);
	
	protected void updateDataOfYesterday(){
		throw new RuntimeException("请先重载 Counter.updateDataOfYesterday 方法");
	}
	
	protected void clearDataOfToday(){
		throw new RuntimeException("请先重载 Counter.clearDataOfToday 方法");
	}
	
	protected void updateDataOfLastWeek(){
		throw new RuntimeException("请先重载 Counter.updateDataOfLastWeek 方法");
	}
	
	protected void clearDataOfThisWeek(){
		throw new RuntimeException("请先重载 Counter.clearDataOfThisWeek 方法");
	}
	
	protected void updateDataOfLastMonth(){
		throw new RuntimeException("请先重载 Counter.updateDataOfLastMonth 方法");
	}
	
	protected void clearDataOfThisMonth(){
		throw new RuntimeException("请先重载 Counter.clearDataOfThisMonth 方法");
	}

	
	public static void main( String[] args ) {
	    Map<Long, Counts> tmp = new HashMap<Long, Counts>();
	    Counts counts = new Counts();
	    counts.setBufferCounts( 10 );
	    counts.setDbCounts( 10 );
	    tmp.put( 1L, counts );
	    counts.setBufferCounts( counts.getBufferCounts()+1 );
	    
	    System.out.println(counts.getBufferCounts());
	    System.out.println(tmp.get( 1L ).getBufferCounts());
    }
}
